import { Module } from 'vuex';
import { EDITOR_RESET, UPDATE_PAGE_SETTING, CANVAS_FIX, HISTORY, CHECK_UNDO_DISABLE, CHECK_REDO_DISABLE, EDITOR_ACTION, SET_EDITOR, GET_EDITOR, STORAGE_EDITOR, UPDATE_CURRENT_ID, GET_CURRENT_COMPONENT, UPDATE_COMPONENT_PROPS, UPDATE_COMPONENT_LIST, GET_EDITOR_PAGE, UPDATE_LAYER_PROPS, UPDATE_PAGE_PROPS, UPDATE_PAGE, COPY_COMPONENTS, PASTE_COMPONENTS, DETELE_COMPONENTS, MOVE_COMPONENTS, UNDO, REDO } from '@/utils/Const';
import Storage from '@/utils/Storage';
import { ITextComponentProps, IImageComponentProps, IShapeComponentProps } from 'fow-code-components/lib/defaultProps.d';
import { IGlobalDataProps } from '../index';
import { uuid } from '@/utils';
import { cloneDeep } from 'lodash-es';
import { MoveDirection } from '@/plugins/dataOperations';
export interface IPageProps {
	title: string; // 页面标题
	coverImg?: string; // 封面图
	desc?: string; // 描述
	props: { [key: string]: any }; // 全局属性设置
	setting: { [key: string]: any }; // 插件配置
}

export interface IEditorProps {
	components: IComponentData[]; // 添加的组件
	currentId: string; // 选中的组件ID
	copyComponents?: IComponentData; // 被复制的组件
	page: IPageProps; // 页面属性
	histories: IHistoryProps[]; // 历史记录
	historyIndex: number; // 当前历史记录的操作位置
	canvasFix: boolean; // 截图时取消box-shadow
}

export interface IHistoryProps {
	id: string; // id
	componentId?: string; // 组件id
	type: 'add' | 'delete' | 'update';
	isRoot?: boolean; // 页面属性
	data?: any; // 数据
	index?: number; // 组件的位置
}

export interface IComponentData {
	id?: string; // 组件Id
	name: 'h-text' | 'h-image' | 'h-shape'; // 组件名称
	layerName?: string; // 图层名称
	isHidden?: boolean; // 是否隐藏
	isLocked?: boolean; // 是否锁定
	props: Partial<ITextComponentProps & IImageComponentProps & IShapeComponentProps>; // 组件的属性
}
const pageDefaultProps = { backgroundColor: '#ffffff', backgroundImage: '', backgroundRepeat: 'no-repeat', backgroundSize: 'cover', height: '560px' };

// 最大历史记录
const maxHistoryNumber = 20;
const pushHistory = (state: IEditorProps, historyRecord: IHistoryProps) => {
	// 组件操作，重置历史索引
	if (state.historyIndex !== -1) {
		// 如有十条历史记录，撤回5条，在操作组件
		// 剔除大于当前历史记录的数据
		state.histories = state.histories.slice(0, state.historyIndex);
		state.historyIndex = -1;
	}
	if (state.histories.length < maxHistoryNumber) {
		state.histories.push(historyRecord);
	} else {
		state.histories.shift();
		state.histories.push(historyRecord);
	}
};
let timer: any = 0;
// 防抖函数
let debounce = (callback: () => void, ms = 1000) => {
	if (timer) {
		clearTimeout(timer);
	}
	timer = setTimeout(() => {
		callback();
	}, ms);
};

let editor: Module<IEditorProps, IGlobalDataProps> = {
	namespaced: true,
	state: {
		components: [],
		currentId: '',
		page: { title: '未命名标题', desc: '未命名标题', props: pageDefaultProps, setting: {} },
		histories: [],
		historyIndex: -1,
		canvasFix: false,
		...(Storage.get<IEditorProps>(STORAGE_EDITOR, 1) || {}),
	},
	getters: {
		[GET_EDITOR](state: IEditorProps): IEditorProps {
			return state;
		},
		[GET_EDITOR_PAGE](state: IEditorProps): IPageProps {
			return state.page;
		},
		// 获取选中的组件
		[GET_CURRENT_COMPONENT](state: IEditorProps): IComponentData | undefined {
			return state.components.find(item => item.id === state.currentId);
		},
		// 是否可撤回
		[CHECK_UNDO_DISABLE]: (state: IEditorProps) => {
			return state.histories.length === 0 || state.historyIndex === 0;
		},
		// 是否重做
		[CHECK_REDO_DISABLE]: (state: IEditorProps) => {
			return state.histories.length === 0 || state.historyIndex === -1 || state.historyIndex === state.histories.length;
		},
	},
	mutations: {
		// 添加组件画布中
		[SET_EDITOR](state: IEditorProps, payload: IComponentData): void {
			payload.id = uuid();
			payload.layerName = `图层${state.components.length + 1}`;
			payload.isHidden = false;
			payload.isLocked = false;
			state.components.push(payload);
			pushHistory(state, {
				id: uuid(),
				componentId: payload.id,
				type: 'add',
				data: cloneDeep(payload),
			});
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		// 更新选中的ID
		[UPDATE_CURRENT_ID](state: IEditorProps, id: string): void {
			state.currentId = id;
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		[HISTORY](state: IEditorProps, history: IHistoryProps) {
			pushHistory(state, history);
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		// 更新组件props
		[UPDATE_COMPONENT_PROPS](state: IEditorProps, { currentId, key, v }): void {
			let id = currentId || state.currentId;
			let componentsProps = state.components.find(item => item.id === id);
			if (componentsProps) {
				let oldVal = componentsProps.props[key]; // 老的值
				let newVal = v; // 新的值
				// 更新组件属性
				componentsProps.props[key] = v;
				const store = this as any;
				debounce(() => {
					store.commit(`editor/${HISTORY}`, {
						id: uuid(),
						componentId: id,
						type: 'update',
						data: {
							oldVal,
							newVal,
							key,
						},
					});
				});
				Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
			}
		},
		// 更新组件排序
		[UPDATE_COMPONENT_LIST](state: IEditorProps, list: IComponentData[]) {
			state.components = list;
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		// 更新图层属性
		[UPDATE_LAYER_PROPS](state: IEditorProps, { layerId, key, v }): void {
			let componentsProps = state.components.find(item => item.id === layerId);
			if (componentsProps) {
				componentsProps[key] = v;
				Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
			}
		},
		// 更新页面属性
		[UPDATE_PAGE_PROPS](state: IEditorProps, { key, v }) {
			state.page.props[key] = v;
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		// 更新页面setting
		[UPDATE_PAGE_SETTING](state: IEditorProps, { key, v }) {
			state.page.setting[key] = v;
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		// 更新页面
		[UPDATE_PAGE](state: IEditorProps, { key, v }) {
			state.page[key] = v;
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		// 复制
		[COPY_COMPONENTS](state: IEditorProps) {
			const currentComponent = state.components.find(component => component.id === state.currentId);
			if (currentComponent) {
				state.copyComponents = currentComponent;
			}
		},
		// 粘贴
		[PASTE_COMPONENTS](state: IEditorProps) {
			if (state.copyComponents) {
				const clone: IComponentData = cloneDeep(state.copyComponents);
				clone.id = uuid();
				clone.layerName = `图层${state.components.length + 1}`;
				clone.isHidden = false;
				clone.isLocked = false;
				state.components.push(clone);
				pushHistory(state, {
					id: uuid(),
					componentId: clone.id,
					type: 'add',
					data: cloneDeep(clone),
				});
				Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
			}
		},
		// 删除
		[DETELE_COMPONENTS](state: IEditorProps) {
			const componentsList = state.components.filter(component => component.id !== state.currentId);
			// 删除的数据
			const componentData = state.components.find(component => component.id === state.currentId) as IComponentData;
			// 删除的当前位置
			const componentIndex = state.components.findIndex(component => component.id === state.currentId);
			state.components = componentsList;
			pushHistory(state, {
				id: uuid(),
				componentId: state.currentId,
				type: 'delete',
				index: componentIndex,
				data: componentData,
			});
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		// 移动
		[MOVE_COMPONENTS](state: IEditorProps, data: { direction: MoveDirection; amount: number }) {
			const currentComponent = state.components.find(component => component.id === state.currentId);
			if (currentComponent) {
				const oldTop: number = parseInt(currentComponent.props.top as string);
				const oldLeft: number = parseInt(currentComponent.props.left as string);
				let key: string = '';
				let v: string = '';
				switch (data.direction) {
					case 'Up':
						key = 'top';
						v = oldTop - data.amount + 'px';
						break;
					case 'Down':
						key = 'top';
						v = oldTop + data.amount + 'px';
						break;
					case 'Left':
						key = 'left';
						v = oldLeft - data.amount + 'px';
						break;
					case 'Right':
						key = 'left';
						v = oldLeft + data.amount + 'px';
						break;
					default:
						break;
				}
				const store = this as any;
				store.commit(`editor/${UPDATE_COMPONENT_PROPS}`, { key, v });
				Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
			}
		},
		// 撤销
		[UNDO](state: IEditorProps) {
			if (state.historyIndex === -1) {
				// 从未撤销过从最后一个开始
				state.historyIndex = state.histories.length - 1;
			} else {
				// 撤销过从上次的位置开始
				state.historyIndex--;
			}
			const history = state.histories[state.historyIndex];
			switch (history.type) {
				case 'add':
					state.components = state.components.filter(item => item.id !== history.componentId);
					break;
				case 'delete':
					state.components.splice(history.index as number, 0, history.data);
					break;
				case 'update':
					let componentData = state.components.find(item => item.id == history.componentId) as IComponentData;
					componentData.props[history.data.key] = history.data.oldVal;
					break;
				default:
					break;
			}
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		// 重做
		[REDO](state: IEditorProps) {
			const history = state.histories[state.historyIndex];
			switch (history.type) {
				case 'add':
					state.components.push(history.data);
					break;
				case 'delete':
					state.components = state.components.filter(item => item.id !== history.componentId);
					break;
				case 'update':
					let componentData = state.components.find(item => item.id == history.componentId) as IComponentData;
					componentData.props[history.data.key] = history.data.newVal;
					break;
				default:
					break;
			}
			state.historyIndex++;
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		[CANVAS_FIX](state: IEditorProps, payload: boolean) {
			state.canvasFix = payload;
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
		[EDITOR_RESET](state: IEditorProps) {
			state.components = [];
			state.currentId = '';
			state.page = { title: '未命名标题', desc: '未命名标题', props: pageDefaultProps, setting: {} };
			state.histories = [];
			state.historyIndex = -1;
			state.canvasFix = false;
			Storage.set<IEditorProps>(STORAGE_EDITOR, state, 1);
		},
	},
	actions: {
		[EDITOR_ACTION]({ commit }, payload: IComponentData): void {
			commit(SET_EDITOR, payload);
		},
	},
};

export default editor;
